<?php

/**
 * 商标管理系统 v1.0.1
 *
 * 商业运营到ubtm.cn官网进行授权使用。
 *
 * (c) cighsen02 <xiayu@959602.com>
 *
 * Create at：2025.05.01
 * Update at: 2025.06.27
*/

namespace App\Http\Middleware;

use App\Exceptions\JsonDecodeException;
use App\Exceptions\JsonResponseException;
use Closure;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;

use function json_decode;
use function json_last_error;
use function str_starts_with;

/**
 * 重定义 Passport 响应格式
 */
class AfterPassportResponse
{
    /**
     * 处置
     *
     * @param Request $request
     * @param Closure $next
     * @return JsonResponse
     * 
     * @throws JsonDecodeException|JsonResponseException
     */
    public function handle(Request $request, Closure $next)
    {
        $response = $next($request);

        if ($this->isPassportRequest($request) && str_starts_with($response->headers->get('Content-Type'), 'application/json')) {

            $data = json_decode($response->getContent(), true);

            if (json_last_error() !== JSON_ERROR_NONE) {
                throw new JsonDecodeException('Invalid response format');
            }

            // 自定义失败响应
            if (isset($data['error'])) {
                throw new JsonResponseException($data['message'], $response->getStatusCode());
            }

            return new JsonResponse([
                'status'    => true,
                'message'   => 'success',
                'data'      => $data
            ]);
        }

        return $response;
    }

    /**
     * 是否为 Passport
     *
     * @param Request $request
     * @return bool
     */
    protected function isPassportRequest(Request $request): bool
    {
        // 判断请求是否包含 Authorization 头部且为 Bearer Token
        if ($request->bearerToken()) {
            return true;
        }

        // 判断请求路径是否以 /oauth 开头
        if (str_starts_with($request->getPathInfo(), '/oauth')) {
            return true;
        }

        // 判断请求是否针对 Passport 的 token 端点
        if ($request->is('oauth/token') || $request->is('oauth/token/refresh')) {
            return true;
        }

        return false;
    }
}
